<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

use think\facade\Env;
use app\index\model\Redis;
use think\Db;

// +----------------------------------------------------------------------
// | Swoole设置 php think swoole:server 命令行下有效
// +----------------------------------------------------------------------
return [
    // 扩展自身配置
    'host'         => '0.0.0.0', // 监听地址
    'port'         => 9508, // 监听端口
    'type'         => 'socket', // 服务类型 支持 socket http server
    'mode'         => '', // 运行模式 默认为SWOOLE_PROCESS
    'sock_type'    => '', // sock type 默认为SWOOLE_SOCK_TCP
    'swoole_class' => '', // 自定义服务类名称

    // 可以支持swoole的所有配置参数
    'daemonize'    => false,
    'pid_file'     => Env::get('runtime_path') . 'swoole_server.pid',
    'log_file'     => Env::get('runtime_path') . 'swoole_server.log',

    // 事件回调定义
    'onOpen'       => function ($server, $request) {
        echo "server: handshake success with fd{$request->fd}\n";
    },

    'onMessage' => function ($server, $frame) {
        //echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        $data = json_decode($frame->data,true);
        switch ($data['type']){
            case 101:
                // 更新用户当前客户端ID并改为在线状态
                Db::name('user')->where('id',$data['uid'])->update(['fd'=>$frame->fd,'status'=>1]);
                // 读取用户信息
                $user_info = Db::name('user')->where('id',$data['uid'])->field('avatar,id,username,login_time,des,fd')->find();
                // 将用户存储到在线用户列表
                Redis::hset('online_user',$user_info['id'],json_encode(['fd'=>$user_info['fd'],'username'=>$user_info['username'],'avatar'=>$user_info['avatar'],'logintime'=>date('Y-m-d H:i:s',$user_info['login_time']),'uid'=>$user_info['id'],'des'=>$user_info['des']]));
                // 获取在线用户数据
                $online_user = Redis::hgetall('online_user');
                // 告诉所有用户，有新的用户上线了
                foreach ($online_user as $k => $v){
                    $user = json_decode($v,true);
                    if($user['fd'] != $frame->fd){
                        $server->push($user['fd'], json_encode(['code'=>101,'fd'=>$user['fd'],'uid'=>$user['uid'],'username'=>$user['username'],'des'=>$user['des'],'online_user'=>$online_user]));
                    }
                }
                // 单独给用户发送信息
                $server->push($frame->fd,json_encode(['code'=>101,'fd'=>$frame->fd,'uid'=>$user_info['id'],'username'=>$user_info['username'],'des'=>$user_info['des'],'online_user'=>$online_user]));
                break;
            case 102:
                // 获取用户信息
                $user_from = Db::name('user')->where('fd',$frame->fd)->field('id,fd')->find();
                $user_to = Db::name('user')->where('id',$data['to_id'])->field('id,fd')->find();
                // 存储消息
                $key = $user_from['id'].'_'.$user_to['id'];
                $e_key = $user_to['id'].'_'.$user_from['id'];
                $msg_key = Redis::key_exists($key) ? $key : $e_key;
                Redis::lpush($msg_key,json_encode(['code'=>102,'content'=>$data['content'],'from_id'=>$user_from['id'],'to_id'=>$user_to['id']]));
                // 接收私聊并发送消息
                if($user_to['fd']){
                    $server->push($user_to['fd'],json_encode(['code'=>102,'content'=>$data['content'],'from_id'=>$user_from['id'],'to_id'=>$user_to['id'],'type'=>1]));
                }
                $server->push($user_from['fd'],json_encode(['code'=>102,'content'=>$data['content'],'from_id'=>$user_from['id'],'to_id'=>$user_to['id'],'type'=>0]));
                break;
            case 103:
                // 获取用户信息
                $user_from = Db::name('user')->where('fd',$frame->fd)->field('id,fd')->find();
                $user_to = Db::name('user')->where('id',$data['to_id'])->field('id,fd')->find();
                // 存储消息
                $key = $user_from['id'].'_'.$user_to['id'];
                $e_key = $user_to['id'].'_'.$user_from['id'];
                $msg_key = Redis::key_exists($key) ? $key : $e_key;
                Redis::lpush($msg_key,json_encode(['code'=>103,'img'=>$data['img'],'from_id'=>$user_from['id'],'to_id'=>$user_to['id']]));
                // 接收到图片消息
                if($user_to['fd']){
                    $server->push($user_to['fd'],json_encode(['code'=>103,'img'=>$data['img'],'from_id'=>$user_from['id'],'to_id'=>$user_to['id'],'type'=>1]));
                }
                $server->push($user_from['fd'],json_encode(['code'=>103,'img'=>$data['img'],'from_id'=>$user_from['id'],'to_id'=>$user_to['id'],'type'=>0]));
                break;
            case 105:
                // 用户加入群组
                $user = Db::name('user')->where('fd',$frame->fd)->field('id,fd')->find();
                // mysql存储房间信息，为了多群组实现
                if(!Db::name('chat_room')->where(['uid'=>$user['id'],'fd'=>$user['fd'],'room_id'=>$data['roomId']])->field('id')->find()){
                    Db::name('chat_room')->insert(['room_id'=>$data['roomId'],'uid'=>$user['id'],'fd'=>$user['fd']]);
                }
                // redis存储
                $user_key = 'room_user_'.$data['roomId'];
                if(!Redis::sismember($user_key,$frame->fd)){
                    Redis::sadd($user_key,$frame->fd);
                }
                break;
            case 112:
                // 获取用户信息
                $user_from = Db::name('user')->where('fd',$frame->fd)->field('id')->find();
                // 接收群组文本消息
                $online_user = Redis::hgetall('online_user');
                $user_info = json_decode($online_user[$user_from['id']],true);
                $user_key = 'room_user_'.$data['roomId'];
                $user_list = Redis::smembers($user_key);
                // 存储群组消息
                $msg_key = 'room_chat_'.$data['roomId'];
                Redis::lpush($msg_key,json_encode(['code'=>112,'content'=>$data['content'],'uid'=>$user_from['id'],'avatar'=>$user_info['avatar'],'username'=>$user_info['username'],'type'=>0]));
                // 向所有用户发送消息
                foreach ($user_list as $v) {
                    $user = Db::name('user')->where('fd',$v)->field('id')->find();
                    if($v == $frame->fd){
                        $server->push($v,json_encode(['code'=>112,'content'=>$data['content'],'type'=>1,'uid'=>$user['id'],'roomId'=>$data['roomId']]));
                    } else {
                        $server->push($v,json_encode(['code'=>112,'content'=>$data['content'],'uid'=>$user['id'],'type'=>0,'roomId'=>$data['roomId']]));
                    }
                }
                break;
            case 113:
                // 获取用户信息
                $user_from = Db::name('user')->where('fd',$frame->fd)->field('id')->find();
                // 接收群组图片消息
                $online_user = Redis::hgetall('online_user');
                $user_info = json_decode($online_user[$user_from['id']],true);
                $user_key = 'room_user_'.$data['roomId'];
                $user_list = Redis::smembers($user_key);
                // 存储群组消息
                $msg_key = 'room_chat_'.$data['roomId'];
                Redis::lpush($msg_key,json_encode(['code'=>113,'img'=>$data['img'],'uid'=>$user_from['id'],'avatar'=>$user_info['avatar'],'username'=>$user_info['username'],'type'=>0]));
                // 像所有用户发送消息
                foreach ($user_list as $v) {
                    $user = Db::name('user')->where('fd',$v)->field('id')->find();
                    if($v == $frame->fd){
                        $server->push($v,json_encode(['code'=>113,'img'=>$data['img'],'uid'=>$user['id'],'type'=>1,'roomId'=>$data['roomId']]));
                    } else {
                        $server->push($v,json_encode(['code'=>113,'img'=>$data['img'],'uid'=>$user['id'],'type'=>0,'roomId'=>$data['roomId']]));
                    }
                }
                break;
            case 108:
                // 发布朋友圈处理
                $online_user = Redis::hgetall('online_user');
                foreach ($online_user as $k => $v){
                    $user = json_decode($v,true);
                    $server->push($user['fd'], json_encode(['code'=>108,'circle'=>$data['circle']]));
                }
            default:
                break;
        }
    },

    'onRequest' => function ($request, $response) {
        $response->end("<h1>Hello Swoole. #" . rand(1000, 9999) . "</h1>");
    },

    'onClose' => function ($ser, $fd) {
        $is_user = Db::name('user')->where('fd',$fd)->field('id')->find();
        // 将用户从在线用户列表中剔除并更新在线状态为离线
        Db::name('user')->where('fd',$fd)->update(['status'=>0,'fd'=>0]);
        Redis::hdel('online_user',$is_user['id']);
        $online_user = Redis::hgetall('online_user');
        // 删除聊天室内的人
        $chat_room = Db::name('chat_room')->where('uid',$is_user['id'])->field('room_id,id')->select();
        foreach ($chat_room as $k => $v){
            $key = 'room_user_'.$v['room_id'];
            if(Redis::key_exists($key)){
                // 移除该房间的在线用户
                Redis::srem($key,$fd);
                // 并删除mysql中的数据
                Db::name('chat_room')->where('id',$v['id'])->delete();
            }
        }

        // 告诉所有用户，有用户下线了
        foreach ($online_user as $k => $v){
            $user = json_decode($v,true);
            if($user['fd'] != $fd){
                $ser->push($user['fd'], json_encode(['code'=>101,'fd'=>$user['fd'],'uid'=>$user['uid'],'des'=>$user['des'],'username'=>$user['username'],'online_user'=>$online_user]));
            }
        }

    },
];
